﻿using Batman.Cms.Core;
using Microsoft.AspNetCore.Hosting;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Loader;

namespace Batman.Cms.Loaders
{
    public static class PluginLoader
    {
        private static readonly string PluginFloder = "Plugins";

        private static readonly string PluginJson = "plugin.json";

        private static readonly string[] PluginDevFolders = new[] { "bin", "Debug", "netcoreapp2.1" };

        private static List<PluginInfo> _plugins { get; set; }

        public static List<PluginInfo> GetPlugins(this IHostingEnvironment env)
        {
            if (_plugins == null)
            {
                if (env == null) throw new Exception("请传入env初始加载插件信息");

                _plugins = new List<PluginInfo>();

                var pluginFullPath = env.IsDevelopment() ?
                    Path.Combine(env.ContentRootPath, "..", PluginFloder) :
                    Path.Combine(env.ContentRootPath, PluginFloder);

                var pluginDirectories = Directory.GetDirectories(pluginFullPath);

                foreach (var pluginDirectory in pluginDirectories)
                {
                    var dirInfo = new DirectoryInfo(pluginDirectory);
                    var jsonFile = dirInfo.GetFiles(PluginJson).FirstOrDefault();
                    if (jsonFile == null) continue;

                    var json = File.ReadAllText(jsonFile.FullName);
                    var pluginInfo = JsonConvert.DeserializeObject<PluginInfo>(json);
                    pluginInfo.Path = pluginDirectory;

                    var assemblyPath = env.IsDevelopment() ?
                        Path.Combine(pluginDirectory, Path.Combine(PluginDevFolders), pluginInfo.FileName) :
                        Path.Combine(pluginDirectory, pluginInfo.FileName);


                    pluginInfo.Assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(assemblyPath);

                    pluginInfo.AssemblyPath = Path.GetDirectoryName(assemblyPath);

                    _plugins.Add(pluginInfo);
                }
            }

            return _plugins;
        }
    }
}
